package com.bigoloo.gwt.jalaliwidget.client;

/**
 * Created with IntelliJ IDEA.
 * User: Bahiraei
 * Date: 12/24/12
 * Time: 11:09 AM
 * To change this template use File | Settings | File Templates.
 */
/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.editor.client.adapters.TakesValueEditor;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.user.datepicker.client.DatePicker;

import java.util.Date;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;


public class JalaliDateBox extends Composite
        {



    public class DateBoxHandler implements ValueChangeHandler<String>,
            FocusHandler, BlurHandler, ClickHandler, KeyDownHandler,ChangeListener,
            CloseHandler<PopupPanel> {

        public void onBlur(BlurEvent event) {
            if (isDatePickerShowing() == false) {
                updateDateFromTextBox();
            }
        }

        public void onClick(ClickEvent event) {
            showDatePicker();
        }

        public void onClose(CloseEvent<PopupPanel> event) {
            // If we are not closing because we have picked a new value, make sure the
            // current value is updated.
            if (allowDPShow) {
                updateDateFromTextBox();
            }
        }

        public void onFocus(FocusEvent event) {
            if (allowDPShow && isDatePickerShowing() == false) {
                showDatePicker();
            }
        }

        public void onKeyDown(KeyDownEvent event) {
            switch (event.getNativeKeyCode()) {
                case KeyCodes.KEY_ENTER:
                case KeyCodes.KEY_TAB:
                    updateDateFromTextBox();
                    // Deliberate fall through
                case KeyCodes.KEY_ESCAPE:
                case KeyCodes.KEY_UP:
                    hideDatePicker();
                    break;
                case KeyCodes.KEY_DOWN:
                    showDatePicker();
                    break;
            }
        }

          @Override
        public void onValueChange(ValueChangeEvent<String> event) {
            hideDatePicker();
            preventDatePickerPopup();
            box.setFocus(true);
        }

        @Override
        public void onChange(Widget sender) {
            hideDatePicker();
            preventDatePickerPopup();
            box.setFocus(true);
        }
    }

    private void updateDateFromTextBox() {
        box.setText("");
        box.setText(picker.getPersianShortDate());
        }

    /**
     * Default style name added when the date box has a format error.
     */
    private static final String DATE_BOX_FORMAT_ERROR = "dateBoxFormatError";

    /**
     * Default style name.
     */
    public static final String DEFAULT_STYLENAME = "gwt-DateBox";

    private final PopupPanel popup;
    private final TextBox box = new TextBox();
    private final JalaliDatePicker picker;
    private LeafValueEditor<Date> editor;

    private boolean allowDPShow = true;
    private boolean fireNullValues = false;

    /**
     * Create a date box with a new {@link com.google.gwt.user.datepicker.client.DatePicker}.
     */
    public JalaliDateBox() {
        this(new JalaliDatePicker(), null);
    }




    public JalaliDateBox(JalaliDatePicker picker, Date date) {
        this.picker = picker;
        this.popup = new PopupPanel(true);


        popup.addAutoHidePartner(box.getElement());
        popup.setWidget(picker);
        popup.setStyleName("dateBoxPopup");

        initWidget(box);
        setStyleName(DEFAULT_STYLENAME);

        DateBoxHandler handler = new DateBoxHandler();
        picker.addChangeListener(handler);
        box.addFocusHandler(handler);
        box.addBlurHandler(handler);
        box.addClickHandler(handler);
        box.addKeyDownHandler(handler);
        box.setDirectionEstimator(false);
        popup.addCloseHandler(handler);
        setValue(date);
    }

    /**
     * Returns a {@link com.google.gwt.editor.client.adapters.TakesValueEditor} backed by the JalaliDateBox.
     */


    /**
     * Gets the current cursor position in the date box.
     *
     * @return the cursor position
     *
     */
    public int getCursorPos() {
        return box.getCursorPos();
    }

    /**
     * Gets the date picker.
     *
     * @return the date picker
     */
    public JalaliDatePicker getDatePicker() {
        return picker;
    }

    /**
     * Returns true iff the date box will fire {@code ValueChangeEvents} with a
     * date value of {@code null} for invalid or empty string values.
     */
    public boolean getFireNullValues() {
        return fireNullValues;
    }

    /**
     * Gets the format instance used to control formatting and parsing of this
     * {@link com.bigoloo.gwt.jalaliwidget.client.JalaliDateBox}.
     *
     * @return the format
     */


    /**
     * Gets the date box's position in the tab index.
     *
     * @return the date box's tab index
     */
    public int getTabIndex() {
        return box.getTabIndex();
    }

    /**
     * Get text box.
     *
     * @return the text box used to enter the formatted date
     */
    public TextBox getTextBox() {
        return box;
    }

    /**
     * Get the date displayed, or null if the text box is empty, or cannot be
     * interpreted.
     *
     * @return the current date value
     */


    /**
     * Hide the date picker.
     */
    public void hideDatePicker() {
        popup.hide();
    }

    /**
     * Returns true if date picker is currently showing, false if not.
     */
    public boolean isDatePickerShowing() {
        return popup.isShowing();
    }

    /**
     * Returns true if the date box is enabled, false if not.
     */
    public boolean isEnabled() {
        return box.isEnabled();
    }

    /**
     * Sets the date box's 'access key'. This key is used (in conjunction with a
     * browser-specific modifier key) to automatically focus the widget.
     *
     * @param key the date box's access key
     */
    public void setAccessKey(char key) {
        box.setAccessKey(key);
    }

    /**
     * Sets whether the date box is enabled.
     *
     * @param enabled is the box enabled
     */
    public void setEnabled(boolean enabled) {
        box.setEnabled(enabled);
    }

    /**
     * Sets whether or not the date box will fire {@code ValueChangeEvents} with a
     * date value of {@code null} for invalid or empty string values.
     */
    public void setFireNullValues(boolean fireNullValues) {
        this.fireNullValues = fireNullValues;
    }

    /**
     * Explicitly focus/unfocus this widget. Only one widget can have focus at a
     * time, and the widget that does will receive all keyboard events.
     *
     * @param focused whether this widget should take focus or release it
     */
    public void setFocus(boolean focused) {
        box.setFocus(focused);
    }

    /**
     * Sets the format used to control formatting and parsing of dates in this
     * {@link com.bigoloo.gwt.jalaliwidget.client.JalaliDateBox}. If this {@link com.bigoloo.gwt.jalaliwidget.client.JalaliDateBox} is not empty, the contents of date
     * box will be replaced with current contents in the new format.
     *
     * @param format the new date format
     */


    /**
     * Sets the date box's position in the tab index. If more than one widget has
     * the same tab index, each such widget will receive focus in an arbitrary
     * order. Setting the tab index to <code>-1</code> will cause this widget to
     * be removed from the tab order.
     *
     * @param index the date box's tab index
     */
    public void setTabIndex(int index) {
        box.setTabIndex(index);
    }

    /**
     * Set the date.
     */
    public void setValue(Date date) {
        setValue(date, false);
    }

    public void setValue(Date date, boolean fireEvents) {
   //     setValue(picker.getValue(), date, fireEvents, true);
    }

    /**
     * Parses the current date box's value and shows that date.
     */
    public void showDatePicker() {
              popup.showRelativeTo(this);
    }



    private void preventDatePickerPopup() {
        allowDPShow = false;
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            public void execute() {
                allowDPShow = true;
            }
        });
    }


}

